﻿using Inovout.Models;
using NHibernate.Criterion;
using NHibernate.Mapping;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;

namespace Inovout.Repositories
{
    public class DataObjectRepository<TDataObject> : BaseRepository<TDataObject>, IRepository<TDataObject> where TDataObject : DataObject
    {
        public override void Save(TDataObject dataObject)
        {
            if (!ValueComparer.DefaultValueEquals(dataObject.Id))
            {
                dataObject.ModifiedUserName = Thread.CurrentPrincipal.Identity.Name;
            }
            base.Save(dataObject);
        }
        public override IDataObjectPagedSet<TDataObject> FindAll(int pageSize, int pageIndex, Order[] orders, params ICriterion[] criterions)
        {
            return base.FindAll(pageSize, pageIndex, orders == null ? new Order[] { Order.Desc("CreatedTime") } : orders, criterions);
        }

        protected override CriteriaQuery<TDataObject> CreateCriteriaQuery()
        {
            return base.CreateCriteriaQuery().OrderBy(Order.Desc("CreatedTime"));
        }
        public override TDataObject FindById(object id)
        {
            TDataObject dataObject = base.FindById(id);
            //todo:需使用队列批量更新，需按库分别建立队列。队列提交规则暂定为达到一定数量后批量更新或应用退出时批量更新。
            //dataObject.AccessedUserName = Thread.CurrentPrincipal.Identity.Name;
            //base.Save(dataObject);
            return dataObject;
        }
        public override bool IsUnique(object id, string propertyName, object propertyValue, IDictionary<string, object> relationProperties = null)
        {
            List<ICriterion> criterions = new List<ICriterion>();
            DataObjectTypeDescriptor dataObjectTypeDescriptor = DataObjectTypeDescriptor.Get<TDataObject>();
            if (propertyName.Equals(dataObjectTypeDescriptor.IdentifierProperty.Name, StringComparison.InvariantCultureIgnoreCase))
            {
                //主键
                criterions.Add(Restrictions.Eq(propertyName, propertyValue));
            }
            else
            {
                ICriterion idCriteria = (id == null)
                                            ? Expression.IsNull(dataObjectTypeDescriptor.IdentifierProperty.Name)
                                            : Expression.Eq(dataObjectTypeDescriptor.IdentifierProperty.Name, id);
                criterions.Add(
                    Expression.And(Expression.Eq(propertyName, propertyValue),
                                   Expression.Not(idCriteria)));
            }
            if (relationProperties != null)
            {
                criterions.Add(Restrictions.AllEq((IDictionary)relationProperties));
            }
            //存在表示不唯一
            return !base.Exists(criterions.ToArray());
        }
    }
}
